/*
 ------------------------------------------------------------------------------
 Copyright (C) 2006-2007 Team Blur.

 This file is part of the Quantum Engine source code.

 The Quantum Engine source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Quantum Engine source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Quantum Engine source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


#ifndef __FILESYSTEM_H__
#define __FILESYSTEM_H__


/*
 ==============================================================================

 File System:

 No stdio calls should be used by any part of the game, because we need to deal
 with all sorts of directory and separator char issues.
 Throughout the game a forward slash should be used as a separator. The file
 system takes care of the conversion to an OS specific separator, and treats
 all file and directory names as case insensitive.

 All the data access is through a hierarchical file system, but the contents of
 the file system can be transparently merged from several sources.

 The "base path" is the path to the directory holding the executable and all
 game directories. It is considered read only, so files will never be written
 to it. This can be overridden with the "fs_basePath" variable to allow code
 debugging in a different directory. The base path cannot be modified at all
 after startup.

 The "save path" is the path used for all write access, but files can also be
 read from it. On Windows systems the save path is the same as the base path by
 default, but on *nix systems the base path is usually read only. This can be
 overridden with the "fs_savePath" variable to allow code debugging in a
 different directory. The save path cannot be modified at all after startup.

 The "default game directory" is the directory under the paths where data comes
 from by default. This is BASE_DIRECTORY, and cannot be overridden.

 The "current game directory" may be the same as the default game directory, or
 it may be the name of another directory under the paths that should be checked
 for files before looking in the default game directory. This is the basis for
 add-ons. The current game directory is also BASE_DIRECTORY by default, but can
 be overridden with the "fs_game" variable.

 The "base game directory" is an additional directory that will be checked for
 files before looking in the default game directory but after looking in the
 current game directory. This allows mods based on other mods. The base game
 directory is also BASE_DIRECTORY by default, but can be overridden with the
 "fs_baseGame" variable.

 All generated files (screenshots, demos, config files, etc) will always be
 written to the current game directory.

 The current game directory can never be changed while the game is executing.
 This is a precaution against having a malicious server instruct clients to
 write files over areas they shouldn't.

 Clients automatically set the current game directory after receiving a game
 state from the server, so only servers need to worry about setting the
 "fs_game" variable.

 No other directories outside of the game directory will ever be referenced by
 file system functions.

 To save disk space and speed loading, directory trees can be collapsed into
 ZIP files. The files use a ".pk3" extension to prevent users from modifying
 them accidentally, but otherwise they are simply normal ZIP files. A game
 directory can have multiple ZIP files of the form "pak0.pk3", "pak1.pk3", etc.
 ZIP files are searched in descending alphabetical order, and will always take
 precedence over the file system. This allows a pack file distributed as a
 patch to override all the existing data.

 When building a pack file, make sure a config file isn't present in it, or
 configs will never get loaded from disk!

 The file system transparently handles access to files from either a pack file
 or a directory tree.

 The file system can be safely shut down and reinitialized with different
 fs_basePath / fs_savePath / fs_baseGame / fs_game combinations, but all other
 subsystems that rely on it (renderer, sound, GUI, etc) must also be forced to
 restart.

 ==============================================================================
*/

// Reads data from a file, properly handling partial reads.
// Returns the number of bytes read.
int				FS_Read (void *buffer, int size, fileHandle_t f);

// Writes data to a file, properly handling partial writes.
// Returns the number of bytes written.
int				FS_Write (const void *buffer, int size, fileHandle_t f);

// Writes formatted text to a file.
// Returns the number of characters written.
int				FS_Printf (fileHandle_t f, const char *fmt, ...);

// Seeks on a file
void			FS_Seek (fileHandle_t f, int offset, fsOrigin_t origin);

// Returns the offset in a file
int				FS_Tell (fileHandle_t f);

// Causes any buffered data to be written to a file
void			FS_Flush (fileHandle_t f);

// Forces flush on a file being written to
void			FS_ForceFlush (fileHandle_t f);

// Opens the given file for reading, writing, or appending. Will create any
// needed subdirectories (for write and append modes).
// Returns file size, or -1 if the file wasn't found or an error occurred.
int				FS_OpenFile (const char *name, fileHandle_t *f, fsMode_t mode);

// Closes the given file
void			FS_CloseFile (fileHandle_t f);

// Reads a complete file.
// Returns file size, or -1 if the file wasn't found or an error occurred.
// A NULL buffer will just return the file size without loading as a quick
// check for existance (-1 == not present).
// Appends a trailing 0, so string operations are always safe.
int				FS_ReadFile (const char *name, void **buffer);

// Frees the memory allocated by FS_ReadFile
void			FS_FreeFile (const void *buffer);

// Writes a complete file. Will create any needed subdirectories.
// Returns true if the file was written.
bool			FS_WriteFile (const char *name, const void *buffer, int size);

// Copies the given file
void			FS_CopyFile (const char *srcName, const char *dstName);

// Renames the given file
void			FS_RenameFile (const char *oldName, const char *newName);

// Removes the given file
void			FS_RemoveFile (const char *name);

// Returns true if the given file exists in the current game directory.
// This is to determine if writing a file will cause any overwrites.
bool			FS_FileExists (const char *name);

// Returns a list of files and subdirectories that match the given extension
// (which must include a leading '.' and must not contain wildcards).
// If extension is NULL, all the files will be returned and all the
// subdirectories ignored.
// If extension is "/", all the subdirectories will be returned and all the
// files ignored.
// The returned list can optionally be sorted.
const char **	FS_ListFiles (const char *path, const char *extension, bool sort, int *numFiles);

// Returns a list of files and subdirectories that match the given filter.
// The returned list can optionally be sorted.
const char **	FS_ListFilteredFiles (const char *filter, bool sort, int *numFiles);

// Frees the memory allocated by FS_ListFiles and FS_ListFilteredFiles
void			FS_FreeFileList (const char **fileList);

// Returns a list of game mods with all the data needed by the GUI.
// The returned list can optionally be sorted.
modList_t **	FS_ListMods (bool sort, int *numMods);

// Fress the memory allocated by FS_ListMods
void			FS_FreeModList (modList_t **modList);

// Fills a 0 terminated list of checksums for all the pack files currently
// loaded. If the file system is in pure mode, only pure packs will be added to
// the list.
void			FS_LoadedPackChecksums (ulong packChecksums[MAX_PACK_FILES]);

// Fills a 0 terminated list of checksums for all the missing pack files. If
// the file system is in pure mode, only pure packs will be added to the list.
// Returns true if something was added to the missing list.
// This is used to determine if the client should attempt to download any pack
// files from the server.
bool			FS_ComparePackChecksums (const ulong packChecksums[MAX_PACK_FILES], ulong missingPackChecksums[MAX_PACK_FILES]);

// Returns the name of the pack file that matches the given checksum, or NULL
// if no pack file matches
const char *	FS_PackNameForChecksum (ulong checksum);

// Sets pure mode and a list of pure pack checksums, and restarts the file
// system.
// If pure is true, only the pack files that match the given checksums will be
// allowed as data sources. If purePackChecksums is NULL, then all the pack
// files will be marked as pure and allowed as data sources.
// If pure is false, purePackChecksums is ignored and all the pack files will
// be allowed as data sources.
// Make sure all file I/O operations are terminated before restarting the file
// system!
void			FS_Restart (bool pure, const ulong purePackChecksums[MAX_PACK_FILES]);

// Initializes the file system
void			FS_Init (void);

// Shuts down the file system
void			FS_Shutdown (void);


#endif	// __FILESYSTEM_H__
